
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Request } from 'express';
import { Op } from 'sequelize';
import { TUser } from '../models/TUser';
import { TUserLogin } from '../models/TUserLogin';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private jwtService: JwtService) {}

  private readonly jwtSecret = 'nest-service-jwt-secret-key-2024';

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    
      // 白名单URL检查
    if (this.hasUrl(request.url)) {
      return true;
    }

    // 从请求头获取JWT token
    const authHeader = request.headers.authorization;
    const token = authHeader && authHeader.startsWith('Bearer ') 
      ? authHeader.substring(7) 
      : request.headers['auth-token'] || request.query['auth-token'];

    if (!token) {
      throw new UnauthorizedException('缺少认证令牌');
    }

    try {
      // 验证JWT token
      const payload = this.jwtService.verify(token, { secret: this.jwtSecret });
      
      // 验证用户状态
      const userRecord = await TUser.findOne({
        where: {
          id: payload.userId,
          user_status: 1, // 正常状态
          deleted_at: null,
        },
      });

      if (!userRecord) {
        throw new UnauthorizedException('用户状态异常或已被删除');
      }

      // 将用户信息附加到请求对象
      request.user = {
        id: userRecord.id,
        nick: userRecord.nick,
        avatar: userRecord.avatar,
        phone: userRecord.phone,
        role_type: userRecord.role_type,
      };
      return true;
    } catch (error) {
      throw new UnauthorizedException('认证令牌无效或已过期');
    }
  }

  /**
   * 检查URL是否在白名单中
   * @param url 当前请求的URL
   * @returns 是否在白名单中
   */
  private hasUrl(url: string): boolean {
    const whiteList = [
      '/api/access/login-by-account',
      '/api/basic/get-dictionary',
      '/api/basic/send-code',
      '/api/basic/verify-code',
      '/health',
      '/favicon.ico'
    ];
    
    return whiteList.some(item => {
      const cleanItem = item.replace(/\/+/g, '/');
      const cleanUrl = url.replace(/\/+/g, '/');
      return cleanItem === cleanUrl || cleanUrl.startsWith(cleanItem);
    });
  }
}
